Skip to content

fix(notifications): stop toast replay across nav and page reload - #134

Merged
wgordon17 merged 3 commits into
gordon-code:mainfrom
wgordon17:fix/outage-toast-spam
Aug 18, 2026
Merged

fix(notifications): stop toast replay across nav and page reload#134
wgordon17 merged 3 commits into
gordon-code:mainfrom
wgordon17:fix/outage-toast-spam

Conversation

@wgordon17

Copy link
Copy Markdown
Member

Summary

  • ToastContainer's dedup state was component-local, so it reset every time the component remounted — and since it only renders inside Header (mounted for /dashboard but not /settings), navigating away and back replayed a toast for every notification still active in the store, most visibly a GitHub-status outage that can sit unchanged for hours
  • A hard page refresh reproduced the same symptom via a different path: it wipes the notification store itself, so the next poll's unchanged outage looked brand new again
  • Persist the last-toasted message per source to sessionStorage, checked before showing a toast and pruned once a source's notification clears — sessionStorage survives both a same-tab remount and a refresh, so one mechanism covers both triggers without touching notifyTransitions()'s existing unconditional-push behavior

ToastContainer's dedup state was component-local, so it reset on every
mount. Since it only renders inside Header, which the router mounts for
/dashboard but not /settings, navigating away and back unmounted and
remounted it, replaying a toast for every notification still active in
the store — most visibly a GitHub-status outage, which can sit unchanged
in the store for hours. A hard page refresh reproduced the same symptom
via a different path: it wipes the notification store itself, so the
next poll's unchanged outage looks brand new again.

Persist the last-toasted message per source to sessionStorage, checked
before showing a toast and pruned once a source's notification clears
from the store. sessionStorage survives both a same-tab remount and a
refresh, so a single mechanism covers both triggers without touching
notifyTransitions()'s existing unconditional-push behavior.
- Restarts a toast's auto-dismiss timer on message updates instead of
  leaving a stale one from the prior message, which could dismiss the
  toast early
- Reintroduces a short (3s) per-source coalescing throttle for rapid
  bursts of textually-different messages (e.g. a ticking rate-limit
  retry countdown), distinct from the persisted exact-message dedup —
  with a trailing-edge re-check so a suppressed value that's never
  superseded still surfaces once the window elapses, even when
  errors.ts's own same-message no-op guard would otherwise leave it
  permanently stuck
- Wraps sessionStorage read/write in try/catch matching the codebase's
  established pattern, and clears toast dedup state on logout via
  onAuthCleared
Settings > Replace Token previously left poll/notification/toast/
dashboard-cache state and repo/org/tracked-user/view preferences from
the prior identity in place when swapping to a different GitHub
account, since setAuthFromPat never routed through the onAuthCleared
cleanup path a real logout uses.

Detects a login change (case-insensitive) and performs a full reset —
config, view state, IndexedDB cache, and every registered
onAuthCleared callback — matching clearAuth()'s exact ordering, while
leaving same-identity token rotation (e.g. refreshing an expired PAT)
completely unaffected so preferences aren't lost on routine rotation.
@wgordon17
wgordon17 force-pushed the fix/outage-toast-spam branch from c126cb7 to 710b595 Compare August 18, 2026 19:23
@wgordon17
wgordon17 marked this pull request as ready for review August 18, 2026 19:26
@wgordon17
wgordon17 requested a review from a team August 18, 2026 19:26
@wgordon17
wgordon17 merged commit a7314d8 into gordon-code:main Aug 18, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant